package org.cuit.lmq.core.service;

import lombok.extern.slf4j.Slf4j;
import org.cuit.lmq.core.BaseForecastData;
import org.cuit.lmq.core.DecisionTree;
import org.cuit.lmq.core.Suggestions;
import org.cuit.lmq.domain.common.BaseContextHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * @author Seon
 * @date 2023/3/12
 */
@Slf4j
@Service
public class ForecastServiceImpl {

    @Value("${pingpang_system.train-path}")
    private String trainPath;

    public String getSuggestion(BaseForecastData data) {
        String kind = getForecastResult(data);

        StringBuilder suggestion = new StringBuilder();
        String[] split = kind.split("-");
        for (String s : split) {
            int next = (int) (Math.random() * 100);
            if ("devilTrain".equals(s)) {
                int index = next % Suggestions.devilTrainAdvise.length;
                suggestion.append(Suggestions.devilTrainAdvise[index]);
            } else if ("highTrain".equals(s)) {
                int index = next % Suggestions.highTrainAdvise.length;
                suggestion.append(Suggestions.highTrainAdvise[index]);
            } else if ("normalTrain".equals(s)) {
                int index = next % Suggestions.normalTrainAdvise.length;
                suggestion.append(Suggestions.normalTrainAdvise[index]);
            } else if ("lowTrain".equals(s)) {
                int index = next % Suggestions.lowTrainAdvise.length;
                suggestion.append(Suggestions.lowTrainAdvise[index]);
            } else if ("lowEat".equals(s)) {
                int index = next % Suggestions.lowEatAdvise.length;
                suggestion.append(Suggestions.lowEatAdvise[index]);
            } else if ("moreWater".equals(s)) {
                int index = next % Suggestions.moreWaterAdvise.length;
                suggestion.append(Suggestions.moreWaterAdvise[index]);
            } else if ("devilEat".equals(s)) {
                int index = next % Suggestions.devilEatAdvise.length;
                suggestion.append(Suggestions.devilEatAdvise[index]);
            } else if ("normalEat".equals(s)) {
                int index = next % Suggestions.normalEatAdvise.length;
                suggestion.append(Suggestions.normalEatAdvise[index]);
            } else if ("normalSleep".equals(s)) {
                int index = next % Suggestions.normalSleepAdvise.length;
                suggestion.append(Suggestions.normalSleepAdvise[index]);
            } else if ("moreSleep".equals(s)) {
                int index = next % Suggestions.moreSleepAdvise.length;
                suggestion.append(Suggestions.moreSleepAdvise[index]);
            } else if ("highEat".equals(s)) {
                int index = next % Suggestions.highEatAdvise.length;
                suggestion.append(Suggestions.highEatAdvise[index]);
            }
        }
        return suggestion.toString();
    }

        private String getForecastResult(BaseForecastData data) {
        try {

            DecisionTree decision = new DecisionTree(trainPath);//初始化数据

            ArrayList<String> list = new ArrayList<>();
            ArrayList<ArrayList<String>> test = new ArrayList<>();

            Class<BaseForecastData> clazz = BaseForecastData.class;
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
                Method rm = descriptor.getReadMethod();
                String value = (String) rm.invoke(data);
                list.add(value);
            }
            test.add(list);
            decision.forecastData(test);//预测数据并输出结果

            log.info("用户{}预测了自己的智能建议，建议为{}", BaseContextHolder.getCurrentUserId(),decision.kind);

            return decision.kind;
        } catch (IOException | IllegalAccessException | InvocationTargetException | IntrospectionException e) {
            throw new RuntimeException(e);
        }
    }
}
